package com.wyw.hemerocallis.service.comunication;

import com.wyw.hemerocallis.service.AuthorityFeignClient;
import com.wyw.hemerocallis.vo.JwtToken;
import com.wyw.hemerocallis.vo.UsernameAndPassword;
import feign.Feign;
import feign.Logger;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.support.SpringMvcContract;
import org.springframework.stereotype.Service;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Random;

/**
 * 使用原生Feign       Open Feign = Feign + Ribbon
 *
 * @author Mr Wu    yewen.wu.china@gmail.com
 * <p>
 * Update History:
 * Author        Time            Content
 */
@Service
@Slf4j
public class UseFeignApi {

    private final DiscoveryClient discoveryClient;

    public UseFeignApi(DiscoveryClient discoveryClient) {
        this.discoveryClient = discoveryClient;
    }

    /**
     * 使用Feign 原生API调用远端服务
     *  Feign默认配置初始化、设置自定义配置、生成代理对象
     * @param usernameAndPassword
     */
    public JwtToken thinkingInFeign(UsernameAndPassword usernameAndPassword) {
        //生产反射去拿serviceId
        String serviceId = null;
        Annotation[] annotations = AuthorityFeignClient.class.getAnnotations();
        for (Annotation annotation : annotations) {
            if(annotation.annotationType().equals(FeignClient.class)) {
                serviceId = ((FeignClient) annotation).value();
                log.info("get service id from AuthorityFeignClient: {}", serviceId);
                break;
            }
        }
        // 如果服务 id 不存在, 直接抛异常
        if (null == serviceId) {
            throw new RuntimeException("can not get serviceId");
        }

        //通过serviceId 去拿可用服务实例
        List<ServiceInstance> targetInstances = discoveryClient.getInstances(serviceId);
        if (CollectionUtils.isEmpty(targetInstances)) {
            throw new RuntimeException("can not get target instance from serviceId: " +
                    serviceId);
        }

        //随机选择一个服务实例：负载均衡
        ServiceInstance randomInstance = targetInstances.get(new Random().nextInt(targetInstances.size()));
        log.info("choose service instance: {}, {}, {}", serviceId,
                randomInstance.getHost(), randomInstance.getPort());

        //Feign 客户端初始化，必须要配置encoder、decoder、contract
        AuthorityFeignClient feignClient = Feign.builder()//Feign默认配置初始化
                .encoder(new GsonEncoder())
                .decoder(new GsonDecoder())
                .logLevel(Logger.Level.FULL)
                .contract(new SpringMvcContract())
                .target(
                        AuthorityFeignClient.class,
                        String.format("http://%s:%s",
                                randomInstance.getHost(), randomInstance.getPort())
                );

        return feignClient.getTokenByFeign(usernameAndPassword);

    }



}
